package com.docmgmt.mvp.service.impl;

import com.docmgmt.mvp.dto.FileVersionVO;
import com.docmgmt.mvp.entity.FileEntity;
import com.docmgmt.mvp.entity.FileVersionEntity;
import com.docmgmt.mvp.exception.BusinessException;
import com.docmgmt.mvp.exception.ForbiddenException;
import com.docmgmt.mvp.exception.NotFoundException;
import com.docmgmt.mvp.mapper.FileMapper;
import com.docmgmt.mvp.mapper.FileVersionMapper;
import com.docmgmt.mvp.service.FileStorageService;
import com.docmgmt.mvp.service.FileVersionService;
import com.docmgmt.mvp.service.PermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件版本表（v3.0新增version_type支持3种版本类型） 服务实现类
 * </p>
 *
 * @author Dora
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FileVersionServiceImpl extends ServiceImpl<FileVersionMapper, FileVersionEntity> implements FileVersionService {

    private final FileVersionMapper fileVersionMapper;
    private final FileMapper fileMapper;
    private final PermissionService permissionService;
    private final FileStorageService fileStorageService;

    @Override
    public List<FileVersionVO> listFileVersions(Long fileId, Long userId) {
        log.info("查询文件版本列表: fileId={}, userId={}", fileId, userId);

        // 权限检查
        if (!permissionService.checkPermission(userId, "file:" + fileId, "read")) {
            throw new ForbiddenException("无权限查看该文件的版本");
        }

        // 查询文件信息
        FileEntity file = fileMapper.selectById(fileId);
        if (file == null) {
            throw new NotFoundException("文件不存在");
        }

        // 查询所有版本
        List<FileVersionEntity> versions = fileVersionMapper.listVersionsByFileId(fileId);

        // 转换为VO
        return versions.stream()
                .map(this::entityToVO)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileVersionVO restoreVersion(Long fileId, Integer version, Long userId, String comment) {
        log.info("恢复文件版本: fileId={}, version={}, userId={}", fileId, version, userId);

        // 权限检查
        if (!permissionService.checkPermission(userId, "file:" + fileId, "update")) {
            throw new ForbiddenException("无权限恢复该文件的版本");
        }

        // 查询文件
        FileEntity file = fileMapper.selectById(fileId);
        if (file == null) {
            throw new NotFoundException("文件不存在");
        }

        // 查询要恢复的版本
        FileVersionEntity targetVersion = fileVersionMapper.getByFileIdAndVersion(fileId, version);
        if (targetVersion == null) {
            throw new NotFoundException("版本不存在");
        }

        // 1. 先将当前文件保存为新版本
        Integer currentVersion = fileVersionMapper.getLatestVersionNumber(fileId);
        FileVersionEntity currentBackup = FileVersionEntity.builder()
                .fileId(fileId)
                .version(currentVersion + 1)
                .versionType("auto")
                .isMajor(false)
                .storageKey(file.getStoragePath())
                .storageTier("hot")
                .size(file.getFileSize())
                .md5(file.getMd5Hash())
                .editorId(userId)
                .comment("恢复到版本" + version + "前的自动备份")
                .createdAt(LocalDateTime.now())
                .build();
        fileVersionMapper.insert(currentBackup);

        // 2. 更新文件为目标版本
        file.setStoragePath(targetVersion.getStorageKey());
        file.setFileSize(targetVersion.getSize());
        file.setMd5Hash(targetVersion.getMd5());
        file.setLastEditorId(userId);
        file.setLastEditTime(LocalDateTime.now());
        file.setUpdatedAt(LocalDateTime.now());
        fileMapper.updateById(file);

        // 3. 创建一个新版本记录（标记为从版本X恢复）
        Integer newVersion = currentVersion + 2;
        FileVersionEntity restoreRecord = FileVersionEntity.builder()
                .fileId(fileId)
                .version(newVersion)
                .versionType("manual")
                .isMajor(false)
                .storageKey(targetVersion.getStorageKey())
                .storageTier("hot")
                .size(targetVersion.getSize())
                .md5(targetVersion.getMd5())
                .editorId(userId)
                .comment(comment != null ? comment : "从版本" + version + "恢复")
                .createdAt(LocalDateTime.now())
                .build();
        fileVersionMapper.insert(restoreRecord);

        log.info("文件版本恢复成功: fileId={}, 从版本{}恢复, 新版本号={}", fileId, version, newVersion);

        return entityToVO(restoreRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileVersionEntity createVersion(Long fileId, String storageKey, Long size, String md5,
                                           Long editorId, String versionType, String comment) {
        log.info("创建文件版本: fileId={}, versionType={}", fileId, versionType);

        // 获取最新版本号
        Integer latestVersion = fileVersionMapper.getLatestVersionNumber(fileId);
        Integer newVersion = latestVersion + 1;

        // 创建版本记录
        FileVersionEntity versionEntity = FileVersionEntity.builder()
                .fileId(fileId)
                .version(newVersion)
                .versionType(versionType)
                .isMajor(false)
                .storageKey(storageKey)
                .storageTier("hot")
                .size(size)
                .md5(md5)
                .editorId(editorId)
                .comment(comment)
                .createdAt(LocalDateTime.now())
                .build();

        fileVersionMapper.insert(versionEntity);

        log.info("文件版本创建成功: fileId={}, version={}", fileId, newVersion);

        return versionEntity;
    }

    /**
     * 实体转VO
     */
    private FileVersionVO entityToVO(FileVersionEntity entity) {
        String downloadUrl = null;
        try {
            downloadUrl = fileStorageService.generatePresignedUrl(entity.getStorageKey(), 3600);
        } catch (Exception e) {
            log.warn("生成版本下载链接失败: versionId={}", entity.getId(), e);
        }

        return FileVersionVO.builder()
                .id(entity.getId())
                .fileId(entity.getFileId())
                .version(entity.getVersion())
                .versionType(entity.getVersionType())
                .isMajor(entity.getIsMajor())
                .size(entity.getSize())
                .sizeDisplay(formatFileSize(entity.getSize()))
                .md5(entity.getMd5())
                .editorId(entity.getEditorId())
                .editorName("未知用户") // 简化处理，完整版需要查询sys_user
                .comment(entity.getComment())
                .storageTier(entity.getStorageTier())
                .createdAt(entity.getCreatedAt() != null ?
                        entity.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) : null)
                .downloadUrl(downloadUrl)
                .build();
    }

    /**
     * 格式化文件大小
     */
    private String formatFileSize(Long size) {
        if (size == null || size == 0) {
            return "0 B";
        }
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double sizeInUnit = size.doubleValue();

        while (sizeInUnit >= 1024 && unitIndex < units.length - 1) {
            sizeInUnit /= 1024;
            unitIndex++;
        }

        return String.format("%.2f %s", sizeInUnit, units[unitIndex]);
    }
}
